############################################################################################
## gamegraphics.py
##
## This file contains the core for in-game display
##
## @author(s): Shadow
## @documentation: Shadow
##
## Created on October 29, 2009
############################################################################################
import pygame,loaders,gameroot,player,math,monitors


######################################################################################
## GameDrawable
##
## This class represents a drawable object in-game
##
## @author(s): Shadow
## @documentation: Shadow
######################################################################################
class GameDrawable:
    
    ###########################################################
    ## GameDrawable::__init__
    ##
    ## Constructor for the GameDrawable class
    ## Desc: Initializes all of the variables
    ###########################################################
    def __init__(self,root,imgloc):
        #set the drawing surface to our global surface
        self.surface = pygame.display.get_surface()
        #set our root to the game's root
        self.root = root
        
        #load the image passed into this construcor
        self.image=loaders.load_image_alpha(imgloc)
        
        #make trigonometry make sense (the object should face right normally, like on a graph 0 degrees)
        self.image = pygame.transform.rotate(self.image,-90)
        
        #the original image
        self.orig = self.image
        
        
        #x,y, and rotation on screen
        self.xpos=0 
        self.ypos=0
        self.rotation=0
        
        #scale  for this particular drawable
        self.scale=1
            
        #the hit radius of this drawwable (if its needed)    
        self.hitradiusbase = 255/2
        self.hitradius = self.hitradiusbase     
        
        #used to check if the camera zoom has changed
        self.camOld=None
        
    #####################   END __init__   ####################
   
    ###########################################################
    ## GameDrawable::draw
    ##
    ## 
    ## Desc: Draws this gameGrawable to the screen given a particular camera
    ###########################################################
    def draw(self,camera):
        #check if our x is potentially visible using the camera's position
        if self.xpos-self.image.get_width()/2 > (camera.xpos +(self.root.prefs["resolution"][0]/2.0/camera.zoom)) or self.xpos+self.image.get_width()/2 < (camera.xpos-(self.root.prefs["resolution"][0]/2.0/camera.zoom)):# + ((self.xpos-camera.xpos)*camera.zoom + self.root.prefs["resolution"][0]/2)) or self.xpos < (camera.xpos - ((self.xpos+camera.xpos)*camera.zoom  + self.root.prefs["resolution"][0]/2)):
            return None
        #check if our y is potentially visible using the camera's position
        if self.ypos-self.image.get_height()/2 > (camera.ypos +(self.root.prefs["resolution"][1]/2.0/camera.zoom)) or self.ypos+self.image.get_height()/2 < (camera.ypos-(self.root.prefs["resolution"][1]/2.0/camera.zoom)):# + ((self.ypos-camera.ypos)*camera.zoom + self.root.prefs["resolution"][1]/2)) or self.ypos < (camera.ypos - ((self.ypos+camera.ypos)*camera.zoom + self.root.prefs["resolution"][1]/2)):
            return None
        
        #if the camera's zoom has changed,prepare our image using the scale, multiply by zoom
        if self.camOld == None:
            self.orig = pygame.transform.smoothscale(self.image,(int(self.image.get_width()*self.scale*camera.zoom),int(self.image.get_height()*self.scale*camera.zoom)))
            #make sure our hitradius is affected by zoom
            self.hitradius=self.hitradiusbase*camera.zoom
        elif self.camOld.zoom != camera.zoom:
            self.orig = pygame.transform.smoothscale(self.image,(int(self.image.get_width()*self.scale*camera.zoom),int(self.image.get_height()*self.scale*camera.zoom)))
            #make sure our hitradius is affected by zoom
            self.hitradius=self.hitradiusbase*camera.zoom
        
        #rotate the image to the correct
        self.orig = pygame.transform.rotate(self.orig,self.rotation)
        
        #prepare to draw in the correct spot, rotation and zoom makes this tricky...
        #
        # we need to take zoom into consideration, so the closer were zoomed in the further away from
        # other players we seem
        #
        # also the way pygame draws we have to draw to the middle of the image or it wont draw correctly (because rotation in pygame is silly)
        self.drawx = ((self.xpos - camera.xpos)*camera.zoom + self.root.prefs["resolution"][0]/2.0) - (self.orig.get_width()/2.0)
        self.drawy = ((self.ypos - camera.ypos)*camera.zoom + self.root.prefs["resolution"][1]/2.0) - (self.orig.get_height()/2.0)
        
        #draw our final image
        self.surface.blit(self.orig,(self.drawx,self.drawy))
        
        #####################   END draw   ####################
        
###############################   END GameDrawable   #################################  



######################################################################################
## GameCamera
##
## This class represents the bounds of the viewable screen
##
## @author(s): Shadow
## @documentation: Shadow
######################################################################################
class GameCamera:
    
    ###########################################################
    ## GameDrawable::__init__
    ##
    ## Constructor for the GameCamera class
    ## Desc: Initializes all of the variables
    ###########################################################
    def __init__(self,root):
        #position (in world space) and zoom of the camera
        self.xpos=0
        self.ypos=0
        self.zoom=1
    #####################   END __init__   ####################
        
################################   END GameCamera   ##################################


######################################################################################
## GameScreen
##
## This class maintains all of the drawable data in-game
##
## @author(s): Shadow
## @documentation: Shadow
######################################################################################
class GameScreen:
    
    ###########################################################
    ## GameScreen::__init__
    ##
    ## Constructor for the GameScreen class
    ## Desc: Initializes all of the variables
    ###########################################################
    def __init__(self,root):
        #the surface to draw on
        self.surface = pygame.display.get_surface()
        #our game's root
        self.root = root
        
        #a list of all gamedrawables to draw
        self.gameDrawables = []
        
        #the repaint color
        self.backgroundColor = pygame.color.Color("black")
        
    #####################   END __init__   ####################
    
    
    
    ###########################################################
    ## GameScreen::addGameDrawable
    ##
    ## 
    ## Desc: appends a GameDrawable to GameScreens collection
    ###########################################################
    def addGameDrawable(self,gameDrawable):
        self.gameDrawables.append(gameDrawable)
        
    ################   END addGameDrawable   ##################
    
    
    ###########################################################
    ## GameScreen::removeGameDrawable
    ##
    ## 
    ## Desc: removes a GameDrawable from GameScreens collection
    ###########################################################
    def removeGameDrawable(self,gameDrawable):
        self.gameDrawables.remove(gameDrawable)    
        
    ###############   END removeGameDrawable   ################
    
    ###########################################################
    ## GameScreen::renderScreen
    ##
    ## 
    ## Desc: draws all of the gamedrawables in our collection
    ##        also draws the lines in the beckground
    ###########################################################
    def renderScreen(self,camera):
        #repaint the background to start fresh
        self.surface.fill(self.backgroundColor)
       
        #number of gridlines to draw on the screen per axis
        numlines = 5/camera.zoom    #replace the 1 with the zoom
        
        #draw the background lines
        #
        #space the lines in a way that seems like the entire world is grided (for perspective and relativity)
        startx = (camera.xpos*camera.zoom)%(self.root.prefs["resolution"][0]/numlines)
        starty = (camera.ypos*camera.zoom)%(self.root.prefs["resolution"][1]/numlines)
        for i in range(int(numlines+1)):
            pygame.draw.line(self.surface,pygame.Color(0,int(255/(math.fabs(camera.xpos/1000)+1)),0),(((i+1)*(self.root.prefs["resolution"][0]/numlines))-startx,0),(((i+1)*(self.root.prefs["resolution"][0]/numlines))-startx,self.root.prefs["resolution"][1]),3)
        for i in range(int(numlines+1)):
            pygame.draw.line(self.surface,pygame.Color(0,int(255/(math.fabs(camera.ypos/1000)+1)),0),(0,(((i+1)*self.root.prefs["resolution"][1]/numlines)-starty)),(self.root.prefs["resolution"][0],(((i+1)*self.root.prefs["resolution"][1]/numlines)-starty)),3)     
        
        
        #draw all GameDrawables we have in our collection
        for d in self.gameDrawables:
            d.draw(camera) 
        
    #####################   END __init__   ####################
        
################################   END GameCamera   ##################################   
        
        
        
        
        
    
            

        
        